package javax.net.p2p.bio.handler;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.p2p.api.P2PCommand;
import javax.net.p2p.api.P2PWrapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
 * **************************************************
 * @description 
 * @author   karl
 * @version  1.0, 2018-11-3
 * @see HISTORY
 *      Date        Desc          Author      Operation
 *  	2018-11-3   创建文件       karl        create
 * @since 2017 Phyrose Science & Technology (Kunming) Co., Ltd.
 **************************************************/
public class ChatServerHandler implements Runnable {

    private static final Log log = LogFactory.getLog(ChatServerHandler.class);

    private Socket socket;
    private String currentLoginName;
    private boolean running = true;

    private static LinkedBlockingQueue<P2PWrapper<String>> readingMsgs = new LinkedBlockingQueue();

    private static Map<String, PrintWriter> onLineUsers = new ConcurrentHashMap();

    public ChatServerHandler(Socket socket) {
        try {
            socket.setKeepAlive(true);
        } catch (SocketException ex) {

        }
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            System.out.println("获得新客户端连接：" + socket.getRemoteSocketAddress());
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            while (running) {
                try {
                    P2PWrapper<String> msg = (P2PWrapper) ois.readObject();
                    System.out.println("客户端消息->" + msg);
                    PrintWriter pw = null;
                    switch (msg.getCommand()) {
                        case LOGIN:
                            currentLoginName = msg.getData();
                            pw = new PrintWriter(socket.getOutputStream());
                            onLineUsers.put(currentLoginName, pw);
                            msg.setCommand(P2PCommand.CHAT_ALL);
                            msg.setData(currentLoginName + " 加入聊天室.");
                            readingMsgs.add(msg);
                            break;
                        case LOGOUT:
                            pw = onLineUsers.get(currentLoginName);
                            onLineUsers.remove(currentLoginName);
                            msg.setCommand(P2PCommand.CHAT_ALL);
                            msg.setData(currentLoginName + " 退出聊天室.");
                            readingMsgs.add(msg);
                            currentLoginName = null;
                            if (pw != null) {
                                pw.close();
                            }
                            if (socket != null) {
                                try {
                                    socket.close();
                                    socket = null;
                                } catch (IOException ex) {
                                    log.error(ex);
                                }
                            }
                            break;
                        case CHAT_ONE:
                            msg.setFrom(currentLoginName);
                            readingMsgs.add(msg);
                            break;
                        case CHAT_ALL:
                            msg.setData(currentLoginName + " 对所有人说：" + msg.getData());
                            readingMsgs.add(msg);
                            break;
                    }
                    
                } catch (Exception ex) {
                    log.error(ex);
                    break;
                }
            }
            System.out.println("释放新客户端连接：" + socket.getRemoteSocketAddress());
        } catch (IOException ex) {
            log.error(ex);
        }
        if (currentLoginName != null) {
            onLineUsers.remove(currentLoginName);
        }
        if (socket != null) {
            try {
                socket.close();
                socket = null;
            } catch (IOException ex) {
                log.error(ex);
            }
        }
    }

    public static void processChatEvents() {
        Iterator<P2PWrapper<String>> it = readingMsgs.iterator();
        while (it.hasNext()) {
            P2PWrapper<String> msg = it.next();
            switch (msg.getCommand()) {
                case CHAT_ONE:
                    processChatOne(msg.getFrom(), msg.getData());
                    break;
                case CHAT_ALL:
                case LOGIN:
                case LOGOUT:
                    processChatAll(msg.getData());
                    break;
            }
            it.remove();
        }
    }

    public static void processChatOne(String from, String msg) {
        System.out.println("one msg -> " + msg);
        String[] strs = msg.split(":");
        if (strs.length == 2) {
            PrintWriter pw = onLineUsers.get(strs[0].trim());
            if (pw != null) {
                pw.write(from + " 对您说：" + strs[1]);
                pw.flush();
            }

        }
    }

    public static void processChatAll(String msg) {
        System.out.println("all msg -> " + msg);
        Iterator<Map.Entry<String, PrintWriter>> it = onLineUsers.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, PrintWriter> entry = it.next();
            entry.getValue().write(msg);
            entry.getValue().flush();
        }
    }
}
